#include <iostream>
#include <ctime>
#include <cerrno>
#include <cstring>

// [info][2024/10/16 21:25.39][log.cpp:12] xxxxxx

#define DEBUG_LEVEL 0
#define INFO_LEVEL 1
#define ERROR_LEVEL 2
#define DEFAULT_LEVEL DEBUG_LEVEL

#define logger(level, levelName, format, ...)                                                                    \
{                                                                                                                \
    if(level >= DEFAULT_LEVEL)                                                                                   \
    {                                                                                                            \
        time_t cur_time = time(nullptr);                                                                         \
        struct tm* tm = localtime(&cur_time);                                                                    \
        char time_buffer[128];                                                                                   \
        strftime(time_buffer, 31, "%Y/%m/%d %H:%M.%S", tm);                                                      \
        if(level == ERROR_LEVEL)                                                                                 \
        {                                                                                                        \
            printf("[%s][%s][%s:%d] " format " [%d: %s]\n",                                                      \
                levelName, time_buffer, __FILE__, __LINE__, ##__VA_ARGS__, errno, strerror(errno));              \
        }                                                                                                        \
        else                                                                                                     \
        {                                                                                                        \
            printf("[%s][%s][%s:%d] " format "\n", levelName, time_buffer, __FILE__, __LINE__, ##__VA_ARGS__);   \
        }                                                                                                        \
    }                                                                                                            \
}

#define logDebug(format, ...) logger(DEBUG_LEVEL, "debug", format, ##__VA_ARGS__)
#define logInfo(format, ...) logger(INFO_LEVEL, "info", format, ##__VA_ARGS__)
#define logError(format, ...) logger(ERROR_LEVEL, "error", format, ##__VA_ARGS__)

#define markc(format, ...)                                                                                       \
{                                                                                                                \
    printf("***** " format " *****\n", ##__VA_ARGS__);                                                           \
}

#define markcc std::cout << "***** "
#define enter " *****" << std::endl

int main()
{
    logInfo("hello: %d", 1);
    logDebug("hello: %d", 2);
    logError("hello: %d", 3);
    
    markc("mark1: %d", 1);
    markcc << "mark2: " << 2 << enter;

    return 0;
}